package model;

public class FineTrianglePixelization {
	private IPixelizationListener listener=new DummyPixelizationListener(); 
	public float sizeOfPixelCube=0.001f;
	public void doPixelization2D(RoffTriangle triangle){
		int[] order=triangle.getOrder();
		/*
		order[0]=RoffVector3D.X; 
		order[1]=RoffVector3D.Y; 
		order[2]=RoffVector3D.Z;
		*/
		RoffVector3D v1=new RoffVector3D(triangle.getPoint1().getComponent(order[0]),
				triangle.getPoint1().getComponent(order[1]),
				triangle.getPoint1().getComponent(order[2]));
		RoffVector3D v2=new RoffVector3D(triangle.getPoint2().getComponent(order[0]),
				triangle.getPoint2().getComponent(order[1]),
				triangle.getPoint2().getComponent(order[2]));
		RoffVector3D v3=new RoffVector3D(triangle.getPoint3().getComponent(order[0]),
				triangle.getPoint3().getComponent(order[1]),
				triangle.getPoint3().getComponent(order[2]));
		int index_min_X=(int)Math.ceil(GeoUtil.min(v1.x, v2.x, v3.x)/sizeOfPixelCube); 
		int index_max_X=(int)Math.floor(GeoUtil.max(v1.x, v2.x, v3.x)/sizeOfPixelCube);
		double x_=Double.NaN; double y_=Double.NaN; double z_=Double.NaN;
		for (int index_X=index_min_X; index_X<=index_max_X; index_X++){
			double x=index_X*sizeOfPixelCube;
			switch(order[0]){
			case RoffVector3D.X:
				x_=x; break; 
			case RoffVector3D.Y:
				y_=x; break; 
			case RoffVector3D.Z:
				z_=x; break; 
			}
			double t1=(x-v1.getX())/(v2.getX()-v1.getX()); // v1 v2; 
			double t2=(x-v2.getX())/(v3.getX()-v2.getX()); // v2 v3;
			double t3=(x-v3.getX())/(v1.getX()-v3.getX()); // v1 v3 
			double minY=Double.MAX_VALUE; 
			double maxY=Double.MIN_VALUE;
			double yy; 
			if (t1>=0  && t1<=1){
				yy=t1*v2.getY()+(1-t1)*v1.getY(); 
				minY=Math.min(minY, yy); 
				maxY=Math.max(maxY, yy);
			}
			if (t2>=0  && t2<=1){
				yy=t2*v3.getY()+(1-t2)*v2.getY(); 
				minY=Math.min(minY,yy);
				maxY=Math.max(maxY,yy);
			}
			if (t3>=0 && t3<=1){
				yy=t3*v1.getY()+(1-t3)*v3.getY(); 
				minY=Math.min(minY, yy);
				maxY=Math.max(maxY, yy);
			}
			int index_min_Y=(int)Math.ceil(minY/sizeOfPixelCube); 
			int index_max_Y=(int)Math.floor(maxY/sizeOfPixelCube);
			for (int index_Y=index_min_Y; index_Y<=index_max_Y; index_Y++){
				double y=index_Y*sizeOfPixelCube; 
				switch(order[1]){
				case RoffVector3D.X:
					x_=y; break; 
				case RoffVector3D.Y:
					y_=y; break; 
				case RoffVector3D.Z:
					z_=y; break; 
				}
				RoffVector3D n=new RoffVector3D(triangle.getNormal().getComponent(order[0]),
						triangle.getNormal().getComponent(order[1]),
						triangle.getNormal().getComponent(order[2])
						); 
				double z=(-n.x*(x-v1.getX())-n.y*(y-v1.getY())+n.z*v1.getZ())/n.z;
				switch(order[2]){
				case RoffVector3D.X:
					x_=z; break; 
				case RoffVector3D.Y:
					y_=z; break; 
				case RoffVector3D.Z:
					z_=z; break; 
				}
				listener.informs(x_, y_, z_,1); 
			}
		}
	}
	public static void test1(){
		RoffVector3D v1=new RoffVector3D(0,0,0);
		RoffVector3D v2=new RoffVector3D(20,0,0);
		RoffVector3D v3=new RoffVector3D(20,20,0);
		RoffVector3D[] points=new RoffVector3D[]{v1,v2,v3};  
		RoffTriangle t=new RoffTriangle(0,1,2,points); 
		FineTrianglePixelization p=new FineTrianglePixelization(); 
		p.doPixelization2D(t); 		
	}
	public static void test2(){
		RoffVector3D v1=new RoffVector3D(  1.632993 , 0.000000 , -1.154701);
		RoffVector3D v2=new RoffVector3D(  1.632993 ,  0.000000 ,  1.154701);
		RoffVector3D v3=new RoffVector3D(  0.000000 , -1.632993 , -1.154701);
		RoffVector3D[] points=new RoffVector3D[]{v1,v2,v3};  
		RoffTriangle t=new RoffTriangle(0,1,2,points); 
		FineTrianglePixelization p=new FineTrianglePixelization(); 
		p.doPixelization2D(t); 		
	}
	public static void main(String[] args){
		test2(); 
	}
	public IPixelizationListener getListener() {
		return listener;
	}
	public void setListener(IPixelizationListener listener) {
		this.listener = listener;
	}
}
